home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fatted Calf
/
The Fatted Calf.iso
/
Modules
/
BackSpaceModules
/
Source
/
IconMosaicView
/
IconMosaicView.m
< prev
next >
Wrap
Text File
|
1993-01-28
|
8KB
|
317 lines
/* IconMosaicView.m -- copyright 1993 by Christopher Lane */
#import <c.h>
#import <sys/dir.h>
#import <mach-o/loader.h>
#import <appkit/appkit.h>
#import "Thinker.h"
#import "DefaultsTable.h"
#import "IconMosaicView.h"
#define MODULE "IconMosaic"
#define DEFAULTSFILE "Defaults.strings"
#define IMAGEPATHS getDefault("IconMosaicImagePaths")
#define SEGMENTLIST getDefault("IconMosaicSegmentList")
#define IMAGESUFFIXLIST getDefault("IconMosaicImageSuffixList")
#define APPSUFFIXLIST getDefault("IconMosaicApplicationSuffixList")
#define IGNORESECTIONLIST getDefault("IconMosaicIgnoreSectionList")
#define MAXIMUMSIZE getSizeDefault("IconMosaicMaximumSize")
#define MAXIMUMBYTES getIntDefault("IconMosaicMaximumBytes")
#define DENSITYDEFAULTNAME "IconMosaicDensity"
#define DENSITY getFloatDefault(DENSITYDEFAULTNAME)
#define PATHSEPARATOR "/"
#define PATHSEPARATORCHAR (PATHSEPARATOR)[0]
#define TOKENSEPARATOR ":"
#define TOKENSEPARATORCHAR (TOKENSEPARATOR)[0]
#define EXTENSIONSEPARATOR "."
#define EXTENSIONSEPARATORCHAR (EXTENSIONSEPARATOR)[0]
@implementation IconMosaicView
static any_t search(id self)
{
char *path, *paths = NXCopyStringBuffer(IMAGEPATHS);
for(path = strtok(paths, TOKENSEPARATOR); path != NULL; path = strtok(NULL, TOKENSEPARATOR))
[self loadImagesFromDirectory:path];
NX_FREE(paths);
return self;
}
- initFrame:(NXRect *) frameRect
{
char buffer[MAXPATHLEN];
[super initFrame:frameRect];
[self allocateGState];
images = [[List alloc] init];
inspector = field = nil;
thread = NO_CTHREAD;
lock = mutex_alloc();
condition = condition_alloc();
(void) sprintf(buffer,"%s/%s", [[NXApp delegate] moduleDirectory:MODULE], DEFAULTSFILE);
[(defaults = [[DefaultsTable alloc] initFromFile:buffer]) registerDefaults:[NXApp appName]];
maximumSize = MAXIMUMSIZE;
maximumBytes = MAXIMUMBYTES;
srandom(time(NULL));
return self;
}
- drawSelf:(const NXRect *) rects :(int) rectCount
{
if (rects == NULL || rectCount == 0) return self;
PSsetgray(NX_BLACK);
NXRectFill(rects);
return self;
}
- didLockFocus
{
if(thread == NO_CTHREAD) cthread_detach(thread = cthread_fork((cthread_fn_t) search, (any_t) self));
return self;
}
- free
{
mutex_lock(lock); {
[[images freeObjects] free];
(void) cthread_abort(thread);
} mutex_unlock(lock);
return [super free];
}
- oneStep
{
id image;
NXSize size;
unsigned int count;
NXPoint point = { 0, 1 };
condition_signal(condition);
[self scrollRect:&bounds by:&point];
if(((random() % 100) / 100.0) > [density floatValue]) return self;
mutex_lock(lock); {
count = [images count];
} mutex_unlock(lock);
if(count < 1) return self;
mutex_lock(lock); {
[(image = [images objectAt:(random() % count)]) getSize:&size];
} mutex_unlock(lock);
point.x = random() % (int) (bounds.size.width - size.width);
[image composite:NX_SOVER toPoint:&point];
if(field != nil && [field intValue] < count) [field setIntValue:count];
return self;
}
- inspector:sender
{
char buffer[MAXPATHLEN];
if (inspector == nil) {
(void) sprintf(buffer,"%s/%s.nib", [sender moduleDirectory:MODULE], MODULE);
[NXApp loadNibFile:buffer owner:self withNames:NO];
}
return inspector;
}
- inspectorInstalled
{
mutex_lock(lock); {
[field setIntValue:[images count]];
} mutex_unlock(lock);
return self;
}
- (BOOL) useBufferedWindow { return YES; }
- (const char *) windowTitle { return MODULE; }
- setDefault:sender
{
[sender setTag:YES];
if([density tag]) (void) writeDefault(DENSITYDEFAULTNAME, [density stringValue]);
return self;
}
- setDensity:anObject
{
[(density = anObject) setFloatValue:DENSITY];
return self;
}
- (BOOL) loadFromStream:(NXStream *) stream
{
NXSize size;
BOOL result = NO;
NXImage *image = [[NXImage alloc] init];
if([image loadFromStream:stream]) {
[image getSize:&size];
if(size.width <= maximumSize.width && size.height <= maximumSize.height) {
mutex_lock(lock); {
[images addObject:image];
condition_wait(condition, lock);
} mutex_unlock(lock);
result = YES;
}
else [image free];
}
else [image free];
return result;
}
- (BOOL) member:(const char *) item ofSet:(const char *) set
{
BOOL result = NO;
char *r, *s, *buffer = NXCopyStringBuffer(set);
int index, length, itemLength = strlen(item);
r = buffer;
while((s = r) != NULL) {
if((r = index(s, TOKENSEPARATORCHAR)) != NULL) *r++ = '\0';
if((length = strlen(s)) > itemLength) continue;
else index = itemLength - length;
if(result = (strncmp(s, item + index, length) == 0)) break;
}
NX_FREE(buffer);
return result;
}
- loadImagesFromDirectory:(const char *) directory
{
struct stat fs;
NXStream *stream;
struct direct *dp;
char buffer[MAXPATHLEN];
DIR *dirp = opendir(directory);
if(dirp == NULL) return nil;
for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
(void) strcat(strcat(strcpy(buffer, directory), PATHSEPARATOR), dp->d_name);
if(stat(buffer, &fs) == CERROR) continue;
else if(fs.st_mode & S_IFDIR && (dp->d_name)[0] != EXTENSIONSEPARATORCHAR) [self loadImagesFromDirectory:buffer];
else if(fs.st_size <= maximumBytes && [self member:dp->d_name ofSet:IMAGESUFFIXLIST]) {
if((stream = NXMapFile(buffer, NX_READONLY)) != NULL) {
if([self loadFromStream:stream]) {
#ifdef DEBUG
(void) fprintf(stderr, "%s\n", buffer);
}
else {
(void) fprintf(stderr, "%s -- failed\n", buffer);
#endif
}
NXCloseMemory(stream, NX_FREEBUFFER);
}
}
else if(fs.st_mode & S_IEXEC && fs.st_mode & S_IFREG) [self loadImagesFromSegment:buffer];
}
(void) closedir(dirp);
return self;
}
- loadImagesFromSegment:(const char *) filename
{
long offset;
char *buffer;
unsigned int i;
NXStream *stream, *memory;
unsigned long ncmds, nsects;
struct mach_header m_header;
struct load_command l_command;
struct segment_command s_command;
struct section s_section;
if ((stream = NXMapFile(filename, NX_READONLY)) == NULL) return nil;
if (NXRead(stream, &m_header, sizeof(m_header)) == sizeof(m_header) && m_header.magic == MH_MAGIC) {
for (ncmds = m_header.ncmds; ncmds > 0; ncmds--) {
offset = NXTell(stream);
if (NXRead(stream, &l_command, sizeof(l_command)) != sizeof(l_command)) break;
if (l_command.cmd == LC_SEGMENT) {
NXSeek(stream, offset, NX_FROMSTART);
if (NXRead(stream, &s_command, sizeof(s_command)) != sizeof(s_command)) break;
if([self member:s_command.segname ofSet:SEGMENTLIST]) {
for (nsects = 0; nsects < s_command.nsects; nsects++) {
if (NXRead(stream, &s_section, sizeof(s_section)) != sizeof(s_section)) continue;
else if(s_section.size > maximumBytes || [self member:s_section.sectname ofSet:IGNORESECTIONLIST]) continue;
offset = NXTell(stream);
NXSeek(stream, s_section.offset, NX_FROMSTART);
(void) vm_allocate(task_self(), (vm_address_t *) &buffer, (vm_size_t) s_section.size, TRUE);
for (i = 0; i < s_section.size; i++) buffer[i] = NXGetc(stream);
if((memory = NXOpenMemory(buffer, s_section.size, NX_READONLY)) != NULL) {
if([self loadFromStream:memory]) {
#ifdef DEBUG
(void) fprintf(stderr, "%s:%s:%s\n", filename, s_section.segname, s_section.sectname);
}
else {
(void) fprintf(stderr, "%s:%s:%s -- failed\n", filename, s_section.segname, s_section.sectname);
#endif
}
NXCloseMemory(memory, NX_FREEBUFFER);
}
NXSeek(stream, offset, NX_FROMSTART);
}
}
else NXSeek(stream, s_command.cmdsize - sizeof(s_command), NX_FROMCURRENT);
}
else NXSeek(stream, l_command.cmdsize - sizeof(l_command), NX_FROMCURRENT);
}
}
NXCloseMemory(stream, NX_FREEBUFFER);
return self;
}
@end